/*
 * @Author: wangcb
 * @Email: wangcbgg@163.com
 * @Date: 2021-12-16 14:32:04
 * @LastEditTime: 2022-01-04 15:11:17
 * 焦点移动计算逻辑封装
 */
/**
 * 垂直方向边界计算处理
 * @param {DOMRect} curRect 当前元素DOMRect数据
 * @param {DOMRect[]} rects 目标元素DOMRect数据集合
 * @param {number[]} boundary 边界值集合
 */
function vertic(curRect, rects, boundary) {
    // 最小边界值
    const min = Math.min.apply(null, boundary);
    // 未找到最小值需跨界
    if (min === Infinity)
        return -1;
    // 符合边界值集合10px容错
    const bs = boundary.map((b, i) => {
        if (b >= min - 10 && b <= min + 10)
            return i;
        return null;
    });
    // 过滤掉null
    const fits = bs.filter(b => b !== null);
    // 存在多个符合值
    if (fits.length > 1) {
        // 交集长度集合
        const widths = rects.map((rect, i) => {
            const fit = bs[i];
            if (fit !== null) {
                if (rect.left <= curRect.left && rect.right >= curRect.right ||
                    rect.left >= curRect.left && rect.right <= curRect.right)
                    return Infinity; // 完全重叠
                else {
                    if (rect.left > curRect.left)
                        return curRect.right - rect.left; // 靠右
                    return rect.right - curRect.left; // 靠左
                }
            }
            return -Infinity;
        });
        // 最大交集长度
        return widths.indexOf(Math.max.apply(null, widths));
    }
    return boundary.indexOf(min);
}
/**
 * 计算向上最近元素索引
 * @param {DOMRect} curRect 当前元素DOMRect数据
 * @param {DOMRect[]} rects 目标元素DOMRect数据集合
 * @returns {number} 目标索引值
 */
export function upNearest(curRect, rects) {
    let minTop = Infinity; // 最小top值
    // 边界值集合
    const boundary = rects.map((rect) => {
        // 计算最小top值
        if (rect.top < minTop)
            minTop = rect.top;
        // 计算边界值
        if (rect === curRect)
            return Infinity; // 排除当前
        const delta = curRect.top - rect.bottom;
        if (delta >= 0)
            return delta; // 目标排列在当前上侧
        return Infinity;
    });
    // 当前元素已处于最小top及到达边界, 需要跨界
    if (curRect.top <= minTop)
        return -1;
    return vertic(curRect, rects, boundary);
}
/**
 * 计算向下最近元素索引
 * @param {DOMRect} curRect 当前元素DOMRect数据
 * @param {DOMRect[]} rects 目标元素DOMRect数据集合
 * @returns {number} 目标索引值
 */
export function downNearest(curRect, rects) {
    let maxBottom = -Infinity; // 最大bottom值
    // 边界值集合
    const boundary = rects.map((rect) => {
        // 计算最大bottom值
        if (rect.bottom > maxBottom)
            maxBottom = rect.bottom;
        // 计算边界值
        if (rect === curRect)
            return Infinity; // 排除当前
        const delta = rect.top - curRect.bottom;
        if (delta >= 0)
            return delta; // 目标排列在当前下侧
        return Infinity;
    });
    // 当前元素已处于最大right及到达边界, 需要跨界
    if (curRect.bottom >= maxBottom)
        return -1;
    return vertic(curRect, rects, boundary);
}
/**
 * 水平方向边界计算处理
 * @param {DOMRect} curRect 当前元素DOMRect数据
 * @param {DOMRect[]} rects 目标元素DOMRect数据集合
 * @param {number[]} boundary 边界值集合
 */
function horizon(curRect, rects, boundary) {
    // 最小边界值
    const min = Math.min.apply(null, boundary);
    // 未找到最小值需跨界
    if (min === Infinity)
        return -1;
    // 符合边界值集合5px容错
    const bs = boundary.map((b, i) => {
        if (b >= min - 5 && b <= min + 5)
            return i;
        return null;
    });
    // 过滤掉null
    const fits = bs.filter(b => b !== null);
    // 存在多个符合值
    if (fits.length > 1) {
        // 高度差集合
        const heights = rects.map((rect, i) => {
            const fit = bs[i];
            if (fit !== null)
                return Math.abs(curRect.top - rect.top);
            return Infinity;
        });
        // 最小高度差
        return heights.indexOf(Math.min.apply(null, heights));
    }
    return boundary.indexOf(min);
}
/**
 * 计算向左最近元素索引
 * @param {DOMRect} curRect 当前元素DOMRect数据
 * @param {DOMRect[]} rects 目标元素DOMRect数据集合
 * @returns {number} 目标索引值
 */
export function leftNearest(curRect, rects) {
    let minLeft = Infinity; // 最小left值
    // 边界值集合
    const boundary = rects.map((rect) => {
        // 计算最小left值
        if (rect.left < minLeft)
            minLeft = rect.left;
        // 计算边界值
        if (rect === curRect)
            return Infinity; // 排除当前
        const delta = curRect.left - rect.right;
        if (delta >= 0)
            return delta; // 目标排列在当前左侧
        return Infinity;
    });
    // 当前元素已处于最小left及到达边界, 需要跨界
    if (curRect.left <= minLeft)
        return -1;
    return horizon(curRect, rects, boundary);
}
/**
 * 计算向右最近元素索引
 * @param {DOMRect} curRect 当前元素DOMRect数据
 * @param {DOMRect[]} rects 目标元素DOMRect数据集合
 * @returns {number} 目标索引值
 */
export function rightNearest(curRect, rects) {
    let maxRight = -Infinity; // 最大right值
    // 边界值集合
    const boundary = rects.map((rect) => {
        // 计算最大right值
        if (rect.right > maxRight)
            maxRight = rect.right;
        // 计算边界值
        if (rect === curRect)
            return Infinity; // 排除当前
        const delta = rect.left - curRect.right;
        if (delta >= 0)
            return delta; // 目标排列在当前右侧
        return Infinity;
    });
    // 当前元素已处于最大right及到达边界, 需要跨界
    if (curRect.right >= maxRight)
        return -1;
    return horizon(curRect, rects, boundary);
}
